#pragma once

class ScopeHandle
{
	void* handle;
	ScopeHandle(const ScopeHandle& other) : handle(other.handle)
	{
	}

	void operator = (const ScopeHandle& other)
	{
	}

	class _AbstractCloser
	{
	public:
		virtual void Close(void* handle) = 0;
	};

	template<typename _Fty, typename T>
	class _SpecClose : public _AbstractCloser
	{
		_Fty& closeFn;
	public:
		_SpecClose(_Fty& fun) : closeFn(fun)
		{
		}

		void Close(void* handle)
		{
			closeFn((T)handle);
		}
	};

	_AbstractCloser* mCloser;

public:
	template<typename T, typename _Fty>
	ScopeHandle(T& hndl, _Fty& fn) : handle((void*)hndl)
	{
		mCloser = new _SpecClose<_Fty, T>(fn);
	}

	template<typename T>
	ScopeHandle(T& hndl) : handle((void*)hndl)
	{
		mCloser = new _SpecClose<BOOL WINAPI (HANDLE), T>(CloseHandle);
	}

	~ScopeHandle()
	{
		mCloser->Close(handle);
		delete mCloser;
	}
};